package middleware

import (
	"context"
	sentinel "github.com/alibaba/sentinel-golang/api"
	"github.com/alibaba/sentinel-golang/core/flow"
	"github.com/micro/go-micro/v2/errors"
	"github.com/micro/go-micro/v2/server"
	"log"
)

//基于QPS限流
func InitSential() {
	// 务必先进行初始化
	err := sentinel.InitDefault()
	if err != nil {
		log.Fatal(err)
	}

	// 配置一条限流规则
	_, err = flow.LoadRules([]*flow.FlowRule{
		{
			Resource:        "rand_service", //该规则的资源名称
			Count:           1,              //门槛：当每秒达到10次QPS时生效,本地测试改为1尝试
			MetricType:      flow.QPS,       //限流的测量类型:QPS每秒访问数
			ControlBehavior: flow.Reject,    //表示发流量控制模式,默认超过阈值是直接拒绝
		},
	})
	if err != nil {
		log.Fatal(err)
		return
	}
}

//将sentinal的限流的放行拦截方式写到HandlerWrapper中，对微服务进行封装
func LimitFlowWrapper() server.HandlerWrapper {

	return func(handlerFunc server.HandlerFunc) server.HandlerFunc {
		return func(ctx context.Context, req server.Request, rsp interface{}) error {
			entry, err := sentinel.Entry("rand_service")
			if err != nil {
				//拦截规则生效,直接拦截退出
				log.Println("当前访问量超过设定的最大QPS")
				return errors.NotFound("rand-service", "Currently too many visitors, please try again later!")
			} else {
				//未达到拦截标准，正常放行
				//TODO 做一些正常的业务操作，例如校验token是否存在
				//务必保证业务结束后退出
				defer entry.Exit()
				return handlerFunc(ctx, req, rsp)
			}
		}
	}
}
